class_name 敌人脚本 extends CharacterBody2D

var 速度:float = 50.0
var 方向向量:Vector2 = Vector2.DOWN
var 徘徊目标点:Vector2 = Vector2.ZERO

@export var 最大仇恨范围:int = 120
@export var 最小仇恨范围:int = 16
@export var 追击间隔:int = 1
@export_category('敌人状态')
@export var 敌人状态:状态
@onready var animation_tree: AnimationTree = $AnimationTree
@onready var 死亡动画: AnimationPlayer = $死亡动画贴图/死亡动画
@onready var 动画树状态对象 = animation_tree.get("parameters/StateMachine/playback") as AnimationNodeStateMachinePlayback
@onready var 受击框对象: 受击框 = $受击框
@onready var 伤害框对象: 伤害框 = $伤害框
@onready var ray_cast_2d: RayCast2D = $RayCast2D

var 敌方伤害框对象:伤害框


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	受击框对象.hurt.connect(hit.call_deferred)
	伤害框对象.attack.connect(attack.call_deferred)
	伤害框对象.击退量 = 100
	敌人状态 = 敌人状态.duplicate(true)
	敌人状态.死亡信号.connect(死亡信号)
	死亡动画.animation_finished.connect(func (动画名称) -> void:
		if 动画名称 == '死亡':
			queue_free() 
	)
	敌人状态.生命值修改(敌人状态.生命值,敌人状态.最大生命值,self)

# 伤害到其他节点
func attack(受击框对象:受击框) -> void:
	animation_tree.active = false
	await get_tree().create_timer(追击间隔).timeout
	animation_tree.active = true

# 被攻击
func hit(伤害信息:伤害框) -> void:
	敌方伤害框对象 = 伤害信息
	敌人状态.生命值修改(敌人状态.生命值 - 伤害框对象.伤害值,敌人状态.最大生命值,self) 
	velocity = 伤害信息.伤害方向 * 伤害信息.击退量
	动画树状态对象.travel('被击状态')

#死亡
func 死亡信号() -> void:
	animation_tree.active = false
	动画树状态对象.travel('死亡状态')
	死亡动画.play("死亡")

# 每帧执行
func _physics_process(delta: float) -> void:
	if !animation_tree.is_active():
		return 
	# 获取前动画状态
	var state = 动画树状态对象.get_current_node()
	match state:
		'待机状态':
			pass
		'追击状态':
			var 玩家节点 = 获取玩家节点()
			# 如果玩家已经不在屏幕上，或者被删除了，则get_player可能会返回空
			if 玩家节点 is 玩家:
				# 将velocity这个全局移动向量 设置为 当前位置到 目标位置的 归一化向量 用来控制目标移动
				velocity = global_position.direction_to(玩家节点.global_position) * 速度
			else:
				velocity = Vector2.ZERO
			move_and_slide()
		'被击状态':
			# Vector2.move_toward(to: Vector2, delta: float) 返回一个新向量，该向量朝 to 移动了固定的量 delta。不会超过最终值。
			# 这里朝着Vector2.ZERO（0）每次移动被击退距离*delta的距离，如果到0就会停下
			velocity = velocity.move_toward(Vector2.ZERO,敌方伤害框对象.击退量 * delta * 3)
			move_and_slide()
		'徘徊状态':
			velocity = global_position.direction_to(徘徊目标点) * 速度
			move_and_slide()
			
# 设置动画树目标点
func undate_blend_positions(direction_vector:Vector2) -> void:
	伤害框对象.伤害方向 = Vector2(direction_vector.x,-direction_vector.y)
	animation_tree.set("parameters/StateMachine/待机状态/blend_position", direction_vector)
	animation_tree.set("parameters/StateMachine/追击状态/blend_position", direction_vector)
	animation_tree.set("parameters/StateMachine/徘徊状态/blend_position", direction_vector)
	animation_tree.set("parameters/StateMachine/被击状态/blend_position", direction_vector)
	
# 获取玩家节点
func 获取玩家节点() -> 玩家:
	# 从跟节点上获取player分组并返回第一个节点
	return get_tree().get_first_node_in_group("玩家角色")
	
# 是否在视野看到玩家（用来做，如果视线被其他物体（如树）遮挡，将不会进入追逐状态）
func can_see_player() -> bool:
	# 判断是否范围内
	if !is_plauer_in_range(): return false
	var 玩家节点: = 获取玩家节点()
	# 将射线的方向设为玩家方向 (射线的发射点是蝙蝠的位置，所以玩家的位置-蝙蝠位置获得偏移量)
	ray_cast_2d.target_position = 玩家节点.global_position - global_position
	undate_blend_positions(Vector2(ray_cast_2d.target_position.x,-ray_cast_2d.target_position.y).normalized())
	# 判断是否有物体与射线相交 没有则中间无遮挡
	return not ray_cast_2d.is_colliding()

# 判断是否在仇恨范围内
func is_plauer_in_range() -> bool:
	var result = false
	var 玩家节点: = 获取玩家节点()
	if 玩家节点 is 玩家:
		# 获取当前蝙蝠到玩家的直线距离（distance_to返回向量到向量之间的距离）
		var distance_to_player = global_position.distance_to(玩家节点.global_position)
		if distance_to_player < 最大仇恨范围 && distance_to_player > 最小仇恨范围:
			result = true
	return result
	
# 使用随机数断是否进入徘徊状态
func 是否进入徘徊状态() -> bool:
	var state = 动画树状态对象.get_current_node()
	if state == '待机状态' && floor(randf_range(0,100)) == 1 && not can_see_player():
		var directions = [Vector2.RIGHT,Vector2.DOWN,Vector2.LEFT,Vector2.UP]
		var random_dir = directions[randi() % directions.size()]
		# 随机生成移动距离 (例如 50-200 像素)
		var random_distance = randf_range(50.0, 200.0)
		undate_blend_positions(Vector2(random_dir.x,-random_dir.y))
		# 计算目标位置
		徘徊目标点 = global_position + (random_dir * random_distance)
		return true
	else:
		return false
